package cn.xinfei.xdecision.engine.runner.context;

import cn.xinfei.xdecision.common.model.component.strategyout.StrategyOutput;
import cn.xinfei.xdecision.common.vo.FieldInfoVo;
import cn.xinfei.xdecision.engine.runner.executor.NodeHandler;
import com.google.common.collect.Sets;
import org.apache.commons.lang3.StringUtils;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class PipelineMetaInfoContext extends ConcurrentHashMap<String, NodeHandler> {

    public Set<String> getField(Predicate<Map.Entry<String, FieldInfoVo>> predicate) {
        HashSet<String> objects = Sets.newHashSet();
        this.entrySet().stream().forEach(entry -> {
            NodeHandler nodeHandler = entry.getValue();
            Map<String, FieldInfoVo> inputFields = nodeHandler.getInputFields();
            if (null != inputFields) {
                inputFields.entrySet()
                        .stream()
                        .filter(e -> predicate.test(e))
                        .forEach(e -> {
                            FieldInfoVo value = e.getValue();
                            objects.add(value.getFieldCode());
                        });
            }
        });
        return objects;
    }

    public Set<StrategyOutput> getTerminalOutputFields() {
        //遍历当前决策流下的所有节点，将输出变量返回
        Set<StrategyOutput> fieldVoSet = this.entrySet().stream()
                .filter(e -> e.getValue().getOutputFields() != null)
                .map(e -> {
                    Map<String, StrategyOutput> outputFields = e.getValue().getTerminalOutputFields();
                    Set<StrategyOutput> collect = outputFields.entrySet().stream()
                            .filter(m -> {
                                Integer stage = m.getValue().getStage();
                                if (stage != null && stage == 3) {
                                    return true;
                                }
                                return false;
                            })
                            .map(m -> m.getValue())
                            .collect(Collectors.toSet());
                    return collect;
                })
                .reduce((set1, set2) -> {
                    set1.addAll(set2);
                    return set1;
                })
                .orElseGet(HashSet::new);
        return fieldVoSet;
    }
    public Set<StrategyOutput> getOutputField() {
        //遍历当前决策流下的所有节点，将输出变量返回
        Set<StrategyOutput> fieldVoSet = this.entrySet().stream()
                .filter(e -> e.getValue().getOutputFields() != null)
                .map(e -> {
                    Map<String, StrategyOutput> outputFields = e.getValue().getOutputFields();
                    Set<StrategyOutput> collect = outputFields.entrySet().stream()
                            .filter(m -> {
                                Integer stage = m.getValue().getStage();
                                if (stage != null && stage == 3) {
                                    return true;
                                }
                                return false;
                            })
                            .map(m -> m.getValue())
                            .collect(Collectors.toSet());
                    return collect;
                })
                .reduce((set1, set2) -> {
                    set1.addAll(set2);
                    return set1;
                })
                .orElseGet(HashSet::new);
        return fieldVoSet;
    }

    public Set<FieldInfoVo> getInputField() {
        Set<FieldInfoVo> fieldVoSet = new HashSet<>();
        this.entrySet().stream().forEach(entry -> {
            NodeHandler nodeHandler = entry.getValue();
            Map<String, FieldInfoVo> inputFields = nodeHandler.getInputFields();
            if (null != inputFields) {
                inputFields.entrySet()
                        .stream()
                        .filter(e -> {
                            Integer isIn = e.getValue().getIsInput();
                            return isIn == 1;
                        })
                        .forEach(e -> {
                            FieldInfoVo value = e.getValue();
                            fieldVoSet.add(value);
                        });
            }
        });
        return fieldVoSet;
    }
    public Set<FieldInfoVo> getAllInputFields() {
        Set<FieldInfoVo> fieldVoSet = new HashSet<>();
        this.entrySet().stream().forEach(entry -> {
            NodeHandler nodeHandler = entry.getValue();
            Map<String, FieldInfoVo> inputFields = nodeHandler.getInputFields();
            if (null != inputFields) {
                inputFields.entrySet()
                        .stream()
                        .forEach(e -> {
                            FieldInfoVo value = e.getValue();
                            fieldVoSet.add(value);
                        });
            }
        });
        return fieldVoSet;
    }
    public Set<FieldInfoVo> getFieldSourceType(String sourceType) {
        Set<FieldInfoVo> fieldVoSet = new HashSet<>();
        this.entrySet().stream().forEach(entry -> {
            NodeHandler nodeHandler = entry.getValue();
            Map<String, FieldInfoVo> inputFields = nodeHandler.getInputFields();
            if (null != inputFields) {
                inputFields.entrySet()
                        .stream()
                        .filter(e -> {
                            String sType = e.getValue().getSourceType();
                            return StringUtils.isNotEmpty(sType) && sType.equals(sourceType);
                        })
                        .forEach(e -> {
                            FieldInfoVo value = e.getValue();
                            fieldVoSet.add(value);
                        });
            }
        });
        return fieldVoSet;
    }

}
